#include <iostream>
#include "l_utility.hpp"
#include <boost/asio.hpp>


namespace http {
    namespace server3 {

        /************************************************************************
         bind from C++ function to lua function:
         (This function convert from ip address string with dot to unsigned long
              +original function:
                  unsigned long inet_network( const char * cp );
              +lua function:
                  number inet_network(string cp)
        ************************************************************************/
        static int l_inet_network(lua_State* L){
            if(lua_gettop(L)>0 && lua_isstring(L,1)){                
                lua_pushnumber(L, inet_network(luaL_checkstring(L, 1)));
                return 1;
            }
            return 0;
        }

        static int lua_sleep(lua_State *L) {
            //printf("ready to receive new data \n");
            return lua_yield(L,0);
        }

        int  l_register_table_SI(lua_State* L, int n, Util_Table_SI *arr, const char* table_name){
            lua_newtable(L);
            for (; arr->key; arr++) {
                lua_pushstring(L, arr->key);
                lua_pushinteger(L, arr->value);
                lua_rawset(L, -3);
            }
            //Tao mot ban sao của metatable
            lua_pushvalue(L, -1);
            lua_setfield(L, -1, "__index");
            lua_setfield(L, n-1, table_name);
            return 1;
        }

        /* Converts a hex character to its integer value */
        static inline char from_hex(char ch) {
          return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
        }

        /* Converts an integer value to its hex character*/
        static inline char to_hex(char code) {
          static char hex[] = "0123456789abcdef";
          return hex[code & 15];
        }

        /* Returns a url-encoded version of str */
        /* IMPORTANT: be sure to free() the returned string after use */
        static char *fast_url_encode(const char *str) {
          const char *pstr = str;
          char *buf = (char*)malloc(strlen(str) * 3 + 1), *pbuf = buf;
          while (*pstr) {
            if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~')
              *pbuf++ = *pstr;
            else if (*pstr == ' ')
              *pbuf++ = '+';
            else
              *pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15);
            pstr++;
          }
          *pbuf = '\0';
          return buf;
        }

        /* Returns a url-decoded version of str */
        /* IMPORTANT: be sure to free() the returned string after use */
        static char *fast_url_decode(const char *str) {
          const char *pstr = str;
          char *buf = (char*)malloc(strlen(str) + 1), *pbuf = buf;
          while (*pstr) {
            if (*pstr == '%') {
              if (pstr[1] && pstr[2]) {
                *pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]);
                pstr += 2;
              }
            } else if (*pstr == '+') {
              *pbuf++ = ' ';
            } else {
              *pbuf++ = *pstr;
            }
            pstr++;
          }
          *pbuf = '\0';
          return buf;
        }

        static int l_fast_url_decode(lua_State *L) {
            if(lua_isstring(L,1)) {
                char* buf = fast_url_decode(luaL_checkstring(L, 1));
                lua_pushstring(L,buf);
                free(buf);
                return 1;
            }
            return 0;
        }
        static int l_fast_url_encode(lua_State *L) {
            if(lua_isstring(L,1)) {
                char* buf = fast_url_encode(luaL_checkstring(L, 1));
                lua_pushstring(L,buf);
                free(buf);
                return 1;
            }
            return 0;
        }

        //===============================================
        int l_register_utility(lua_State* L){
            lua_register(L, "wait_for_next_request", lua_sleep);
            lua_register(L, "c_inet_network", l_inet_network);
            lua_register(L, "fast_url_decode", l_fast_url_decode);
            lua_register(L, "fast_url_encode", l_fast_url_encode);

            return 1;
        }

    }
}

